package mapper

import (
	"errors"
	"fmt"
	"gitee.com/damengde/treebark/model"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

func NewGormDbMapper[T any](db any, nodeField *model.NodeField) (*GormDbServiceImpl[T], error) {
	// 获取事务
	tx, ok := db.(*gorm.DB)
	if !ok {
		return nil, errors.New("参数类型错误")
	}
	return &GormDbServiceImpl[T]{
		tx:        tx,
		nodeField: nodeField,
	}, nil
}

type GormDbServiceImpl[T any] struct {
	tx        *gorm.DB
	nodeField *model.NodeField
}

func (g *GormDbServiceImpl[T]) UpdateBatch(nodes []*T) error {
	err := g.tx.Save(&nodes).Error
	if err != nil {
		return errors.New("批量更新部门信息失败：" + err.Error())
	}
	return nil
}

func (g *GormDbServiceImpl[T]) DeleteById(id any) error {
	if err := g.tx.Where(fmt.Sprintf("%s = ?", g.nodeField.Id.Column), id).Delete(new(T)).Error; err != nil {
		return errors.New("节点删除失败：" + err.Error())
	}
	return nil
}

func (g *GormDbServiceImpl[T]) SelectById(id any) (node *T, err error) {
	if err := g.tx.Where(fmt.Sprintf("%s = ?", g.nodeField.Id.Column), id).Find(&node).Error; err != nil {
		return node, errors.New("根据id查询节点失败：" + err.Error())
	}
	return node, nil
}

func (g *GormDbServiceImpl[T]) SelectByIds(ids []any) (nodes []*T, err error) {
	if err := g.tx.Where(fmt.Sprintf("%s = IN (?)", g.nodeField.Id.Column), ids).Find(nodes).Error; err != nil {
		return nodes, errors.New("根据id查询节点失败：" + err.Error())
	}
	return
}

func (g *GormDbServiceImpl[T]) SelectDescendentAndLockByTreeId(topParentId any) (nodes []*T, err error) {
	if err = g.tx.Where(fmt.Sprintf("%s = ?", g.nodeField.TreeId.Column), topParentId).Order("lft ASC").
		Clauses(clause.Locking{Strength: "UPDATE"}).Find(&nodes).Error; err != nil {
		return nil, errors.New("根据树根节点id查询节点树失败：" + err.Error())
	}
	return
}

// SelectDescendentById 根据父节点查询所有子节点
func (g *GormDbServiceImpl[T]) SelectDescendentById(parentId any) (nodes []*T, err error) {
	// 根据MPTT算法查询所有子节点
	var parentNode = new(T)
	result := g.tx.Where(fmt.Sprintf("%s = ?", g.nodeField.Id.Column), parentId).Find(parentNode)
	if err = result.Error; err != nil {
		return nodes, errors.New("查询节点信息失败：" + err.Error())
	}
	if result.RowsAffected == 0 {
		return nodes, errors.New("查询的节点信息不存在")
	}
	right := g.nodeField.GetRight(parentNode)
	treeId := g.nodeField.GetTreeId(parentNode)
	left := g.nodeField.GetLeft(parentNode)
	err = g.tx.
		Where(fmt.Sprintf(`%s = ? AND %s > ? AND %s < ?`, g.nodeField.TreeId.Column, g.nodeField.Left.Column, g.nodeField.Right.Column),
			treeId, left, right).Find(&nodes).Error
	if err != nil {
		return nodes, errors.New("查询节点信息失败：" + err.Error())
	}
	return nodes, nil
}

// SaveOrUpdate 查询所有部门
func (g *GormDbServiceImpl[T]) SaveOrUpdate(sdMod *T) error {
	// 更新所有节点
	err := g.tx.Save(sdMod).Error
	if err != nil {
		return errors.New("更新节点信息失败：" + err.Error())
	}
	return nil
}

// Update 更新部门信息
func (g *GormDbServiceImpl[T]) Update(mod *T) error {
	if err := g.tx.Save(&mod).Error; err != nil {
		return errors.New("更新节点信息失败：" + err.Error())
	}
	return nil
}

// Delete 删除节点
func (g *GormDbServiceImpl[T]) Delete(id any) error {
	if err := g.tx.Where(fmt.Sprintf("%s = ?", g.nodeField.Id.Column), id).Delete(new(T)).Error; err != nil {
		return errors.New("节点删除失败：" + err.Error())
	}
	return nil
}

// SelectAllTopParentId 查询所有顶级父节点
func (g *GormDbServiceImpl[T]) SelectAllTopParentId() (tops []*T, err error) {
	result := g.tx.
		Where(fmt.Sprintf("%s IS NULL OR %s = ''", g.nodeField.ParentId.Column, g.nodeField.ParentId.Column)).Find(&tops)
	if err = result.Error; err != nil {
		return tops, errors.New("查询顶级父节点信息失败：" + err.Error())
	}
	if result.RowsAffected == 0 {
		return tops, errors.New("不存在parent_id为空的数据：")
	}
	return tops, nil
}

func (g *GormDbServiceImpl[T]) SelectAllByParentIdAsc(topParentId any) (departs []*T, err error) {
	if err = g.tx.Where(fmt.Sprintf("%s = ?", g.nodeField.TreeId.Column), topParentId).
		Clauses(clause.Locking{Strength: "UPDATE"}).Find(&departs).Error; err != nil {
		return nil, errors.New("根据顶级父节点查询树失败")
	}
	return departs, nil
}

func (g *GormDbServiceImpl[T]) UpdateNewNode(mod *T) error {
	err := g.tx.Save(&mod).Error
	if err != nil {
		return errors.New("更新节点信息失败：" + err.Error())
	}
	return nil
}
